<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2021/3/4
 * Time: 20:15
 */
declare(strict_types=1);

namespace App\Service;
use App\Model\Dao\EventOrderDao;
use App\Model\Dao\MchAccountDao;
use App\Model\Dao\TradeOrderDetailDao;
use App\Model\Dao\TradeOrderDisDao;
use App\Model\Dao\TradeOrderFrozenDao;
use App\Model\Dao\TradeOrderRefundDao;
use App\Model\Dao\TradeOrderThawDao;
use App\Model\Dao\TradeTransDao;
use App\Utils\CustomUtils;
use App\Utils\RedisUtils;
use Hyperf\Di\Annotation\Inject;

class RepairService
{
    /**
     * @Inject()
     * @var TradeOrderDetailDao
     */
    private $TradeOrderDetailDao;

    /**
     * @Inject()
     * @var TradeOrderDisDao
     */
    private $TradeOrderDisDao;

    /**
     * @Inject()
     * @var TradeOrderRefundDao
     */
    private $TradeOrderRefundDao;

    /**
     * @Inject()
     * @var TradeOrderFrozenDao
     */
    private $TradeOrderFrozenDao;

    /**
     * @Inject()
     * @var TradeOrderThawDao
     */
    private $TradeOrderThawDao;

    /**
     * @Inject()
     * @var EventOrderDao
     */
    private $EventOrderDao;

    /**
     * @Inject()
     * @var TradeTransDao
     */
    private $TradeTransDao;

    /**
     * @Inject()
     * @var MchAccountDao
     */
    private $MchAccountDao;

    /**
     * @Inject()
     * @var SettleTradeOrderThawBondService
     */
    private $SettleTradeOrderThawBondService;

    /**
     * @Inject()
     * @var SettleTradeOrderDisFeeService
     */
    private $SettleTradeOrderDisFeeService;

    /**
     * @Inject()
     * @var SettleSalesCommissionService
     */
    private $SettleSalesCommissionService;

    public function handle ($param) {
        switch ($param['type']) {
            case ACCESS_TYPE_TRADE_ORDER:
                $this->repairTradeOrder();
                break;
            case ACCESS_TYPE_TRADE_ORDER_REFUND:
                $this->repairTradeRefund();
                break;
            case ACCESS_TYPE_TRADE_ORDER_DIS_LOOK_INTO:
                $this->repairTradeDisLookInto();
                break;
            case ACCESS_TYPE_TRADE_ORDER_FROZEN:
                $this->repairTradeFrozen();
                break;
            case ACCESS_TYPE_TRADE_ORDER_THAW:
                $this->repairTradeThaw();
                break;
            case ACCESS_TYPE_TRADE_FAIL:
                $this->repairTradeFail();
                break;
            case ACCESS_TYPE_BOND_THAW:
                $this->repairTradeThawBond();
                break;
            case ACCESS_TYPE_EVENT_ORDER_FROZEN:
                $this->repairEvent();
                break;
            case ACCESS_TYPE_WITHDRAW:
                $this->repairTradeWithdraw();
                break;
            case ACCESS_TYPE_TRANS:
                $this->repairTradeTrans();
                break;
            case ACCESS_TYPE_DIS_FEE:
                $this->repairTradeDisFee($param);
                break;
            case ACCESS_TYPE_SALES_COMMISSION:
                $this->repairSalesCommission($param);
                break;
        }
    }

    private function getMchAccountId($mchId) {
        $mchAccount = $this->MchAccountDao->getByMchId($mchId);
        return !empty($mchAccount) ? $mchAccount['id'] : '';
    }

    /**
     * 订单结算repair
     */
    private function repairTradeOrder() {
        $ids = $this->TradeOrderDetailDao->getWhereList([
            'transStatus'   => 6,
            'isSettle'      => 0,
        ], 'createTime', [null, null], ["id", "mchId"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'orderId'       => $value['id'],
                'accessType'    => ACCESS_TYPE_TRADE_ORDER,
                'mchAccountId'  => $mchAccountId
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 退款订单结算repair
     */
    private function repairTradeRefund() {
        $ids = $this->TradeOrderRefundDao->getWhereList([
            'settleStatus' => 0,
        ], 'createTime', [null, null], ["id", "mchId", "handleStatus"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'refundId'      => $value['id'],
                'accessType'    => ACCESS_TYPE_TRADE_ORDER_REFUND,
                'mchAccountId'  => $mchAccountId,
                'handleStatus'  => $value['handleStatus']
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 拒付订单结算repair
     */
    private function repairTradeDisLookInto() {
        $ids = $this->TradeOrderDisDao->getWhereList([
            'settleStatus' => 0,
        ], 'createTime', [null, null], ["id", "mchId", "handleStatus"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'refundId'      => $value['id'],
                'accessType'    => ACCESS_TYPE_TRADE_ORDER_DIS_LOOK_INTO,
                'mchAccountId'  => $mchAccountId,
                'handleStatus'  => $value['handleStatus']
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 冻结订单结算repair
     */
    private function repairTradeFrozen() {
        $ids = $this->TradeOrderFrozenDao->getWhereList([
            'settleStatus' => 0,
        ], 'createTime', [null, null], ["id", "mchId", "handleStatus"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'refundId'      => $value['id'],
                'accessType'    => ACCESS_TYPE_TRADE_ORDER_FROZEN,
                'mchAccountId'  => $mchAccountId,
                'handleStatus'  => $value['handleStatus']
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 解冻结算repair
     */
    private function repairTradeThaw() {
        $ids = $this->TradeOrderThawDao->getWhereList([
            'settleStatus' => 0,
        ], 'createTime', [null, null], ["id", "mchId", "handleStatus"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'refundId'      => $value['id'],
                'accessType'    => ACCESS_TYPE_TRADE_ORDER_THAW,
                'mchAccountId'  => $mchAccountId,
                'handleStatus'  => $value['handleStatus']
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 交易失败结算repair
     */
    private function repairTradeFail() {
        $riskFailIds = $this->TradeOrderDetailDao->getWhereList([
            'transStatus'       => 4,
            'failSettleStatus'  => 0,
        ], 'createTime', [null, null], ["id", "mchId"]);
        $bankFailIds = $this->TradeOrderDetailDao->getWhereList([
            'transStatus'       => 5,
            'failSettleStatus'  => 0,
        ], 'createTime', [null, null], ["id", "mchId"]);

        $ids = array_merge($riskFailIds, $bankFailIds);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'orderId'       => $value['id'],
                'accessType'    => ACCESS_TYPE_TRADE_FAIL,
                'mchAccountId'  => $mchAccountId,
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 事件订单结算repair
     */
    private function repairEvent() {
        $ids = $this->EventOrderDao->getWhereList([
            'settleStatus' => 0,
        ], 'createTime', [null, null], ["id", "mchId", "type", "handleStatus"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'eventOrderId'  => $value['id'],
                'accessType'    => $value['type'],
                'mchAccountId'  => $mchAccountId,
                'handleStatus'  => $value['handleStatus']
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 保证金解冻结算repair
     */
    private function repairTradeThawBond() {
        $this->SettleTradeOrderThawBondService->statAndPush();
    }

    /**
     * 提现订单结算repair
     */
    private function repairTradeWithdraw() {
        $ids = $this->TradeTransDao->getWhereList([
            'type'  => 1,
            'settleStatus' => 0,
        ], 'createTime', [null, null], ["id", "mchId", "handleStatus"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'eventOrderId'  => $value['id'],
                'accessType'    => ACCESS_TYPE_WITHDRAW,
                'mchAccountId'  => $mchAccountId,
                'handleStatus'  => $value['handleStatus']
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 转账订单结算repair
     */
    private function repairTradeTrans() {
        $ids = $this->TradeTransDao->getWhereList([
            'type'  => 2,
            'settleStatus' => 0,
        ], 'createTime', [null, null], ["id", "mchId", "handleStatus"]);

        $i = 0;
        foreach ($ids as $value) {
            $mchAccountId = $this->getMchAccountId($value['mchId']);
            if (empty($mchAccountId)) continue;

            RedisUtils::redisResource()->rPush("MchAccountAccessList", serialize([
                'eventOrderId'  => $value['id'],
                'accessType'    => ACCESS_TYPE_TRANS,
                'mchAccountId'  => $mchAccountId,
                'handleStatus'  => $value['handleStatus']
            ]));
            $i++;
        }

        CustomUtils::xzxDebug("统计修复条数：" . count($ids) . "统计修复入队条数：{$i}");
    }

    /**
     * 拒付处理费结算repair
     * 默认处理的是上个月的
     */
    private function repairTradeDisFee($param) {
        $statStartTime = strtotime(date('Y-m-01', strtotime("first day of last month")));
        $statEndTime = strtotime(date('Y-m-01', time()));
        if (!empty($param['extra']['statMonth'])) {
            $statMonthOfDayOne = $param['extra']['statMonth'] . "-01";
            $statStartTime = strtotime($statMonthOfDayOne);
            $statEndTime = strtotime( "first day of next month", strtotime($statMonthOfDayOne) );
        }
        $this->SettleTradeOrderDisFeeService->statAndPush($statStartTime, $statEndTime);
    }

    /**
     * 佣金结算repair
     */
    private function repairSalesCommission($param) {
        if (!isset($param['extra']['mchNo']) || empty($param['extra']['mchNo'])) {
            CustomUtils::xzxDebug("必须传入mchNo参数");
            return;
        }

        $mchNo = $param['extra']['mchNo'];
        $statStartTime = strtotime(date('Y-m-01', strtotime("first day of last month")));
        $statEndTime = strtotime(date('Y-m-01', time()));
        if (!empty($param['extra']['statMonth'])) {
            $statMonthOfDayOne = $param['extra']['statMonth'] . "-01";
            $statStartTime = strtotime($statMonthOfDayOne);
            $statEndTime = strtotime( "first day of next month", strtotime($statMonthOfDayOne) );
        }
        $this->SettleSalesCommissionService->statAndPush($mchNo, $statStartTime, $statEndTime);
    }

}